*
* An actor which displays a triangle "arrow" pointing to a given
* side. The .bin property is a container in which content can be
- * placed. The arrow position may be controlled via setArrowOrigin().
+ * placed. The arrow position may be controlled via
+ * setArrowOrigin(). The arrow side might be temporarily flipped
+ * depending on the box size and source position to keep the box
+ * totally inside the monitor if possible.
*
*/
const BoxPointer = new Lang.Class({
_init: function(arrowSide, binProperties) {
this._arrowSide = arrowSide;
+ this._userArrowSide = arrowSide;
this._arrowOrigin = 0;
this.actor = new St.Bin({ x_fill: true,
y_fill: true });
}
this.bin.allocate(childBox, flags);
- if (this._sourceActor && this._sourceActor.mapped)
+ if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(this._sourceActor, this._arrowAlignment);
+
+ if (this._shouldFlip()) {
+ switch (this._arrowSide) {
+ case St.Side.TOP:
+ this._arrowSide = St.Side.BOTTOM;
+ break;
+ case St.Side.BOTTOM:
+ this._arrowSide = St.Side.TOP;
+ break;
+ case St.Side.LEFT:
+ this._arrowSide = St.Side.RIGHT;
+ break;
+ case St.Side.RIGHT:
+ this._arrowSide = St.Side.LEFT;
+ break;
+ }
+ this._reposition(this._sourceActor, this._arrowAlignment);
+ }
+ }
},
_drawBorder: function(area) {
},
setPosition: function(sourceActor, alignment) {
+ this._arrowSide = this._userArrowSide;
+
// We need to show it now to force an allocation,
// so that we can query the correct size.
this.actor.show();
if (!this._sourceActor)
return;
- // We need to show it now to force an allocation,
- // so that we can query the correct size.
- this.actor.show();
-
- this._reposition(this._sourceActor, this._arrowAlignment);
+ this.setPosition(this._sourceActor, this._arrowAlignment);
},
_reposition: function(sourceActor, alignment) {
-(this._yPosition + this._yOffset));
},
+ _shouldFlip: function() {
+ let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
+ let boxAllocation = Shell.util_get_transformed_allocation(this.actor);
+ let boxWidth = boxAllocation.x2 - boxAllocation.x1;
+ let boxHeight = boxAllocation.y2 - boxAllocation.y1;
+ let monitor = Main.layoutManager.findMonitorForActor(this.actor);
+
+ switch (this._arrowSide) {
+ case St.Side.TOP:
+ if (boxAllocation.y2 > monitor.y + monitor.height &&
+ boxHeight < sourceAllocation.y1 - monitor.y)
+ return true;
+ break;
+ case St.Side.BOTTOM:
+ if (boxAllocation.y1 < monitor.y &&
+ boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
+ return true;
+ break;
+ case St.Side.LEFT:
+ if (boxAllocation.x2 > monitor.x + monitor.width &&
+ boxWidth < sourceAllocation.x1 - monitor.x)
+ return true;
+ break;
+ case St.Side.RIGHT:
+ if (boxAllocation.x1 < monitor.x &&
+ boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
+ return true;
+ break;
+ }
+
+ return false;
+ },
+
set xOffset(offset) {
this._xOffset = offset;
this._shiftActor();